<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/8/31 0031
 * Time: 12:06
 */

namespace app\api\service;


use app\lib\enum\ScopeEnum;
use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;
use app\api\model\User as UserModel;

class UserToken extends Token
{
    protected $code;
    protected $wxAppID;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    function __construct($code)
    {
        $this->code = $code;
        $this->wxAppID = config('wx.app_id');
        $this->wxAppSecret = config('wx.app_secret');
        $this->wxLoginUrl = sprintf(config('wx.login_url'),
                                    $this->wxAppID,
                                    $this->wxAppSecret,
                                    $this->code);
    }

    public function get(){
        $result = curl_get($this->wxLoginUrl);
//        true转化成数组 否则是个对象
        $wxResult = json_decode($result,true);
        if (empty($wxResult)){
//            不想将错误返回到客户端，所以用tp5的Exception
            throw new Exception('获取session_key及openID时异常，微信内部错误');
        }else{
            $loginFail = array_key_exists('errcode',$wxResult);
            if ($loginFail){
                $this->processLoginError($wxResult);
            }else{
                return $this->grantToken($wxResult);
            }
        }
    }
    private function grantToken($wxResult){
//        拿到openid
//        数据库里看一下，这个openid是不是已经存在
//        如果存在，则不处理；如果不存在，则新增一条user记录
//        生成令牌，准备缓存数据，写入缓存
//        把令牌返回到客户端去
//        key: 令牌
//        value： wxResult, uid, scope
        $openid = $wxResult['openid'];
        $user = UserModel::getByOpenID($openid);
        if ($user){
            $uid = $user->id;
        }else{
            $uid = $this->newUser($openid);
        }
        $cachedValue = $this->prepareCachedValue($wxResult,$uid);
        $token = $this->saveToCache($cachedValue);
        return $token;
    }

    /**
     * 写入缓存
     * @param $cachedValue
     */
    private function saveToCache($cachedValue){
        $key = self::generateToken();
//        json_encode 可以把数组转化成字符串
        $value = json_encode($cachedValue);
//        用缓存时间 来检测是否token失效
        $expire_in = config('setting.token_expire_in');

//        默认文件缓存形式
        $request = cache($key,$value,$expire_in);
        if (!$request){
            throw new TokenException([
                'msg' => '服务器缓存异常',
                'errorCode' => 10005
            ]);
        }
        return $key;
    }
    /**
     * 定义缓存内容
     * @param $wxResult
     * @param $uid
     * @return mixed
     */
    private function prepareCachedValue($wxResult, $uid){
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;
//        scope=16 代表App用户的权限数值
//        $cachedValue['scope'] = 15;
        $cachedValue['scope'] = ScopeEnum::User;
        //        scope=32 代表CMS(管理员)用户的权限数值
//        $cachedValue['scope'] = ScopeEnum::Super;
        return $cachedValue;
    }

    /**
     * 新增一条user记录
     * @param $openid
     * @return mixed
     */
    private function newUser($openid){
        $user = UserModel::create([
            'openid' => $openid
        ]);
        return $user->id;
    }
    private function processLoginError($wxResult){
        throw new WeChatException([
            'msg' => $wxResult['errmsg'],
            'errorCode' => $wxResult['errcode']
        ]);
    }
}